﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using H2.Streams;
using Mystery.SCNR;

namespace Mystery
{
    public class PlayerStartingLocation
    {
        public const int Size = 52;
        public const int Offset = 256;

        public float PositionX;
        public float PositionY;
        public float PositionZ;
        public float FacingDegrees;
        
        public short TeamDesignator;
        public enum TeamDesignatorEnum
        {
            Red = 0,
            Blue = 1,
            Yellow = 2,
            Green = 3,
            Purple = 4,
            Orange = 5,
            Brown = 6,
            Pink = 7,
            Neutral = 8,
        }

        public short BSPIndex;

        public short Gametype1;
        public short Gametype2;
        public short Gametype3;
        public short Gametype4;
        public enum GametypeEnum
        {
            None = 0,
            CaptureTheFlag = 1,
            Slayer = 2,
            Oddball = 3,
            KingOfTheHill = 4,
            Race = 5,
            Juggernaught = 7,
            Territories = 8,
            Assault = 9,
            AllTeamGameTypes = 11,
            AllGameTypes = 12,
            AllExceptCTF = 13,
        }

        public short SpawnType1;
        public short SpawnType2;
        public short SpawnType3;
        public short SpawnType4;
        public enum SpawnTypeEnum
        {
            Both = 0,
            InitialOnly = 1,
            RespawnOnly = 2,
        }

        public short CampaignPlayerType;
        public enum CampaignPlayerTypeEnum
        {
            MasterChief = 0,
            Dervish = 1,
            ChiefMultiplayer,
            EliteMultiplayer
        }

        public void ReadFrom(MapStream map)
        {
            int startOffset = (int)map.Position;

            PositionX = map.ReadFloat();
            PositionY = map.ReadFloat();
            PositionZ = map.ReadFloat();

            FacingDegrees = map.ReadFloat();

            TeamDesignator = map.ReadInt16();

            BSPIndex = map.ReadInt16();

            Gametype1 = map.ReadInt16();
            Gametype2 = map.ReadInt16();
            Gametype3 = map.ReadInt16();
            Gametype4 = map.ReadInt16();

            SpawnType1 = map.ReadInt16();
            SpawnType2 = map.ReadInt16();
            SpawnType3 = map.ReadInt16();
            SpawnType4 = map.ReadInt16();

            CampaignPlayerType = map.ReadInt16At(startOffset + 44, false);
        }

        public void WriteTo(BaseStream map)
        {
            int startOffset = (int)map.Position;

            map.Write(PositionX);
            map.Write(PositionY);
            map.Write(PositionZ);

            map.Write(FacingDegrees);

            map.Write(TeamDesignator);

            map.Write(BSPIndex);

            map.Write(Gametype1);
            map.Write(Gametype2);
            map.Write(Gametype3);
            map.Write(Gametype4);

            map.Write(SpawnType1);
            map.Write(SpawnType2);
            map.Write(SpawnType3);
            map.Write(SpawnType4);

            map.Write(new byte[8]);

            map.Write(CampaignPlayerType);

            map.Write(new byte[6]);
        }

        public static void Generate(Scenario scnr, AISquad[] aiSquads, AIZone[] aiZones, int selectedBSPIndex, bool ignoreVehicleSquads, BaseStream.StatusChangeHandler statusChanged)
        {
            foreach (AISquad s in aiSquads)
            {
                if (s.Ignore) continue;
                if (ignoreVehicleSquads && s.VehicleIndex >= 0) continue;
                //if (selectedBSPIndex >= 0 && selectedBSPIndex != s.BSPIndex) continue;

                if (scnr.PlayerStartingLocations.Count >= 256)
                {
                    statusChanged("Player Starting Location Limit Reached! Some Spawns Will Be Ignored.");
                }

                foreach (AISquad.StartingLocation sl in s.StartingLocations)
                {
                    PlayerStartingLocation psl = new PlayerStartingLocation();
                    scnr.PlayerStartingLocations.Add(psl);

                    psl.PositionX = sl.PositionX;
                    psl.PositionY = sl.PositionY;
                    psl.PositionZ = sl.PositionZ;

                    psl.FacingDegrees = sl.RotationYaw;

                    short bspIndex = aiZones[s.InitalZoneIndex].BSPOrigin;
                    if (bspIndex == 0) bspIndex = (short)selectedBSPIndex;
                    else if (bspIndex == selectedBSPIndex) bspIndex = 0;
                    psl.BSPIndex = bspIndex;

                    psl.Gametype1 = (short)GametypeEnum.AllGameTypes;
                    psl.SpawnType1 = (short)SpawnTypeEnum.Both;
                    psl.CampaignPlayerType = (short)CampaignPlayerTypeEnum.MasterChief;
                }
            }
        }

        public static void Generate(Scenario scnr, int selectedBSPIndex, Placement[] placements, BaseStream.StatusChangeHandler statusChangeHandler)
        {
            foreach (Placement p in placements)
            {
                if (selectedBSPIndex >= 0 && p.BSPIndex != selectedBSPIndex) continue;

                PlayerStartingLocation psl = new PlayerStartingLocation();
                scnr.PlayerStartingLocations.Add(psl);

                psl.PositionX = p.PositionX;
                psl.PositionY = p.PositionY;
                psl.PositionZ = p.PositionZ;

                if (selectedBSPIndex >= 0)
                    psl.BSPIndex = p.BSPIndex;

                psl.FacingDegrees = p.RotationYaw;

                psl.Gametype1 = (short)GametypeEnum.AllGameTypes;
                psl.SpawnType1 = (short)SpawnTypeEnum.Both;
                psl.CampaignPlayerType = (short)CampaignPlayerTypeEnum.MasterChief;
            }
        }
    }
}
